package views

import (
	"context"
	. "fastdp-ops/pkg/server/api/middleware"
	"fastdp-ops/pkg/server/api/models"
	. "fastdp-ops/pkg/server/config"
	. "fastdp-ops/pkg/server/grpc"

	"fastdp-ops/pkg/server/utils" // 引入utils包
	pb "fastdp-ops/proto/exec"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"net/http"
	"strings"
	"sync"
	"time"
)

func Exec(c *gin.Context) {
	hostlist := c.PostFormArray("hostlist")
	if len(hostlist) == 0 {
		Logger.Warn("执行请求缺少主机列表", zap.String("module", c.PostForm("module")), zap.String("taskId", c.PostForm("taskid")))
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
			"错误请求": "未指定主机",
		})
		return
	}
	module := c.PostForm("module")
	taskId := c.PostForm("taskid")

	// 解析Parameters（map[string]string）
	params := make(map[string]string)
	for key, values := range c.Request.PostForm {
		if strings.HasPrefix(key, "params.") {
			realKey := strings.TrimPrefix(key, "params.")
			params[realKey] = values[0]
		}
	}

	if module == "" || taskId == "" || len(params) == 0 {
		Logger.Warn("执行请求参数不完整",
			zap.String("module", module),
			zap.String("taskId", taskId),
			zap.Int("paramCount", len(params)))
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
			"错误请求": "未指定模块/参数/任务id",
		})
		return
	}

	// 获取可用机器列表
	machineList := []models.Machines{}
	if err := DB.Find(&machineList).Error; err != nil {
		Logger.Error("查询数据库机器列表失败", zap.Error(err), zap.String("module", module), zap.String("taskId", taskId))
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "查询数据库机器列表失败: " + err.Error(),
		})
		return
	}

	// 筛选在线主机
	execlist := make([]string, 0)
	hostSet := make(map[string]models.Machines)
	for _, machine := range machineList {
		for _, host := range hostlist {
			if machine.MachineIP == host && machine.Status == 1 {
				if _, exists := hostSet[host]; !exists {
					hostSet[host] = machine
					execlist = append(execlist, host)
				}
			}
		}
	}

	Logger.Info("开始执行模块任务",
		zap.String("module", module),
		zap.String("taskId", taskId),
		zap.Int("targetHosts", len(execlist)),
		zap.Strings("hostList", execlist))

	allResponses := make([]*pb.ExecResponse, 0, len(execlist))
	agentPort := V.GetString("fastdp-agent.port")
	var wg sync.WaitGroup
	var mu sync.Mutex

	for _, host := range execlist {
		wg.Add(1)
		go func(host string) {
			defer wg.Done()
			Logger.Debug("开始处理主机任务", zap.String("host", host), zap.String("module", module), zap.String("taskId", taskId))

			// 其他模块处理
			addr := host + ":" + agentPort
			conn, err := GetClientConn(addr)
			if err != nil {
				Logger.Error("获取主机连接失败",
					zap.String("host", host),
					zap.String("addr", addr),
					zap.Error(err))

				// 使用utils.ErrorResponse统一生成错误响应
				errResp := utils.ErrorResponse(&pb.Execrequest{MachineId: host, TaskId: taskId}, 1, "获取连接失败: "+err.Error())

				mu.Lock()
				allResponses = append(allResponses, errResp)
				mu.Unlock()
				return
			}
			defer conn.Close()

			client := pb.NewExecServiceClient(conn)
			ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
			defer cancel()

			// 构造gRPC请求
			req := &pb.Execrequest{
				MachineId:  host,
				Module:     module,
				Parameters: params,
				TaskId:     taskId,
			}

			resp, err := client.Exec(ctx, req)
			mu.Lock()
			if err != nil {
				Logger.Error("gRPC调用失败",
					zap.String("host", host),
					zap.String("module", module),
					zap.Error(err))
				// 使用utils.ErrorResponse统一生成错误响应
				allResponses = append(allResponses, utils.ErrorResponse(req, 500, "gRPC调用失败: "+err.Error()))
			} else {
				Logger.Debug("gRPC调用成功", zap.String("host", host), zap.String("module", module))
				allResponses = append(allResponses, resp)
			}
			mu.Unlock()
		}(host)
	}

	wg.Wait()
	Logger.Info("模块任务执行完成",
		zap.String("module", module),
		zap.String("taskId", taskId),
		zap.Int("totalHosts", len(execlist)))

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"results": allResponses,
	})
}
